package com.example.abc.service;

import com.example.abc.amqp.MqMsgSender;
import com.example.abc.common.Constants;
import com.example.abc.common.DataTableRequest;
import com.example.abc.common.DataTableResponse;
import com.example.abc.dto.MyUserDetails;
import com.example.abc.dto.Profile;
import com.example.abc.dto.account.AuthorityTreeDto;
import com.example.abc.exception.ClientException;
import com.example.abc.repository.UserAuthorityDao;
import com.example.abc.util.AliyunOssUtil;
import com.example.abc.util.ImageUtil;
import com.example.abc.util.SessionUtils;
import com.example.abc.websocket.msg.WsBaseMessage;
import com.example.abc.websocket.msg.LogoutMsg;
import com.example.abc.websocket.msg.WsMessageFactory;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.RowBounds;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.context.SecurityContextRepository;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.ByteArrayInputStream;
import java.util.List;
import java.util.UUID;

import com.example.abc.entity.Account;
import com.example.abc.repository.AccountDao;

@Service
public class AccountService {
    public static final Logger logger = LoggerFactory.getLogger(AccountService.class);

    @Resource
    private AccountDao accountDao;

    @Resource
    private UserAuthorityDao userAuthorityDao;

    @Resource
    private MqMsgSender mqMsgSender;

    @Resource
    private SessionUtils sessionUtils;

    public int insert(Account pojo) {
        return accountDao.insert(pojo);
    }

    public int insertSelective(Account pojo) {
        return accountDao.insertSelective(pojo);
    }

    public int insertList(List<Account> pojos) {
        return accountDao.insertList(pojos);
    }

    public int update(Account pojo) {
        return accountDao.update(pojo);
    }

    public Account findByUsername(String username) {
        return accountDao.findByUsername(username);
    }

    // 注册
    public void register(Account account) {
        Account other = accountDao.findByUsername(account.getUsername());
        if (other != null) {
            throw new ClientException("username already exists");
        }
        account.setPlaintextPassword(account.getPassword());
        account.setPassword(new BCryptPasswordEncoder().encode(account.getPassword()));
        account.setUid(UUID.randomUUID().toString());
        Short enabled = 1;
        account.setEnabled(enabled);
        accountDao.insertSelective(account);
    }

    public DataTableResponse seach(DataTableRequest dataTableRequest) {
        DataTableResponse response = new DataTableResponse();
        RowBounds rowBounds = new RowBounds(dataTableRequest.getStart(), dataTableRequest.getLength());
        Long total = accountDao.seachCount(dataTableRequest);
        List<Account> list = accountDao.seach(dataTableRequest, rowBounds);
        response.setRecordsTotal(total);
        response.setData(list);
        response.setDraw(dataTableRequest.getDraw());
        return response;
    }

    public Account findById(Long id) {
        return accountDao.findById(id);
    }

    public List<AuthorityTreeDto> getUserAuthTree(Long id) {
        Account account = accountDao.findById(id);
        return userAuthorityDao.getUserAuthTree(account.getUid());
    }

    // 保存用户权限
    public void saveAccountAuth(String uid, List<Long> authorityIds) {
        // 1. 更新权限。先删除，然后添加新的权限
        if (authorityIds == null || authorityIds.size() == 0) {
            userAuthorityDao.deleteByUid(uid);
        } else {
            userAuthorityDao.deleteByUid(uid);
            userAuthorityDao.saveAccountAuth(uid, authorityIds);
        }


        // 2. logout user
        Account account = accountDao.findByUid(uid);
        logger.info(" ---------- >>> logout user({}) start ",account.getUsername());
        sessionUtils.expireUserSessions(account.getUsername());
        logger.info(" ---------- >>> logout user end. ");

        // 3. 通知用户重新登录系统，将消息发送到消息队列
        LogoutMsg logoutMsg = new LogoutMsg("system",uid,"权限变更，需要重新登录系统");
        mqMsgSender.send(logoutMsg);


    }

    public String saveAvatar(MyUserDetails account, String base64Avatar) {
        byte[] imagedata = ImageUtil.toBytes(base64Avatar);
        ByteArrayInputStream bais = new ByteArrayInputStream(imagedata);
        String key = Constants.ossRootDir + "account/avatar/" + account.getUid() + ".png";
        AliyunOssUtil.upload(key, bais, imagedata.length);

        accountDao.updateAvatar(account.getUid(), key);
        String avatar_url = AliyunOssUtil.toFullOssUrl(key);
        account.setAvatar_url(avatar_url);

        return avatar_url;
    }

    public Account updateProfile(Profile profile) {
        if (StringUtils.isBlank(profile.getRealName())) {
            profile.setRealName(null);
        }
        if (StringUtils.isBlank(profile.getPassword())) {
            profile.setPassword(null);
        } else {
            profile.setPassword(new BCryptPasswordEncoder().encode(profile.getPassword()));
        }

        accountDao.updateProfile(profile);

        return accountDao.findByUid(profile.getUid());
    }
}
